﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace TunaInterpreter.SyntaxCheck
{

    public class SyntaxChecker
    {


        public static void check(string source)
        {
            string[] reservedKeywords = { "int", "float", "string", "jumpnij", "print", "println" };

            string[] lines = source.Split(new[] { '\r', '\n' });

            string labelPattern = @"^(:)\w+\s*$";
            Regex label = new Regex(labelPattern);
            string intDefPattern = @"^int\s*\w*\s*$";
            Regex intDef = new Regex(intDefPattern);
            string floatDefPattern = @"^float\s*\w*\s*$";
            Regex floatDef = new Regex(floatDefPattern);
            string stringDefPattern = @"^string\s*\w*\s*$";
            Regex stringDef = new Regex(stringDefPattern);
            string jumpnijProcPattern = @"^jumpnij\s*\w*\s*$";
            Regex jumpnijProc = new Regex(jumpnijProcPattern);
            string printProcPattern = @"^print\s*((\w*)|(\%.*\%\&))\s*$";
            Regex printProc = new Regex(printProcPattern);
            string printlnProcPattern = @"^println\s*((\w*)|(\%.*\%\&))\s*$";
            Regex printlnProc = new Regex(printlnProcPattern);
            string ifOpPattern = @"^[\w\s\=]*?\?\s*\w+\s*\:\s*\w*\s*$";
            Regex ifOp = new Regex(ifOpPattern);
            string assignOpPattern = @"^(\w+\s*?=(\s*\w+\s*)([\+\-\*\/]\s*\w+\s*)*)$";
            Regex assignOp = new Regex(assignOpPattern);
            foreach (string line in lines)
            {
                if (line.Trim().Length > 0)
                {
                    if (line.ToCharArray()[0] == ':')
                    {
                        if (label.IsMatch(line))
                        {
                            continue;
                        }
                        throw new Exception("Syntax error label definition");
                    }

                    if (line.Contains('?') && line.Contains(':') && !line.Contains('\'') && !line.Contains('\"'))
                    {
                        if (ifOp.IsMatch(line))
                        {
                            continue;
                        }
                        throw new Exception("Syntax error in IF");
                    }

                    string[] lineElements = line.Split(new[] { ' ', '=' });
                    if (lineElements.Count() > 1 && reservedKeywords.Contains(lineElements[0]))
                    {
                        switch (lineElements[0])
                        {
                            case "int":
                                if (intDef.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error int definition");
                                break;
                            case "float":
                                if (floatDef.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error float definition");
                                break;
                            case "string":
                                if (stringDef.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error string definition");
                                break;
                            case "jumpnij":
                                if (jumpnijProc.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error in jump call");
                                break;
                            case "print":
                                if (printProc.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error in print call");
                                break;
                            case "println":
                                if (printProc.IsMatch(line))
                                {
                                    continue;
                                }
                                throw new Exception("Syntax error in println call");
                                break;

                        }
                    }
                    if (assignOp.IsMatch(line))
                    {
                        continue;
                    }
                    throw new Exception("Syntax error");
                }
            }
        }

    }
}
